package com.fsxgt.datagrid.ds.component;

import static com.fsxgt.datagrid.ds.utils.JdbcConstants.MYSQL;
import static com.fsxgt.datagrid.ds.utils.JdbcConstants.ORACLE;
import static com.fsxgt.datagrid.ds.utils.JdbcConstants.POSTGRESQL;
import static com.fsxgt.datagrid.ds.utils.JdbcConstants.SQL_SERVER;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fsxgt.datagrid.ds.bo.DatasourceJdbcBO;
import com.fsxgt.datagrid.ds.dao.DatasourceJdbcMapper;
import com.fsxgt.datagrid.ds.exception.DsException;
import com.fsxgt.datagrid.ds.handler.DbHandler;
import com.fsxgt.datagrid.ds.handler.Hbase20xsqlHandler;
import com.fsxgt.datagrid.ds.handler.MongodbHandler;
import com.fsxgt.datagrid.ds.handler.RdbmsHandler;
import com.fsxgt.datagrid.ds.tool.MetaSqlInterface;
import com.fsxgt.datagrid.ds.tool.SqlToolFactory;
import com.fsxgt.datagrid.ds.utils.AESUtil;
import com.fsxgt.datagrid.ds.utils.JdbcConstants;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;

@Service
public class QueryComponent {

	protected static final Logger logger = LoggerFactory.getLogger(QueryComponent.class);
	@Autowired
	private DatasourceJdbcMapper datasourceJdbcMapper;
	

	private  Cache<Long, DbHandler> cacheQuerySqlHandler = CacheBuilder.newBuilder()

			// 设置并发数(以获取当前操作系统cpu数来确定并发数)
			.concurrencyLevel(Runtime.getRuntime().availableProcessors())
			// 设置初始容量
			.initialCapacity(10)
			// 设置最大存储量
			.maximumSize(100)
			.expireAfterAccess(2 * 60, TimeUnit.SECONDS)
			.removalListener(new RemovalListener<Long, DbHandler>() {
				@Override
				public void onRemoval(RemovalNotification<Long, DbHandler> notification) {
					closeHandler(notification.getValue());
					logger.info("QuerySqlFactory:"+notification.getKey() + "-" + notification.getValue() + " is remove");
				}
			})
			// 构建
			.build();
	
	public  DbHandler getHandler(Long id) throws DsException{
		return getHandler(id,true);
	}
	
	public  DbHandler getHandler(Long id, boolean useCache) throws  DsException
	 {
		DbHandler dbHandler = null;
		
		try {
			if (useCache) {
				dbHandler = cacheQuerySqlHandler.get(id, new Callable<DbHandler>() {

					@Override
					public DbHandler call() throws Exception {
						// TODO Auto-generated method stub
						DatasourceJdbcBO bo = (DatasourceJdbcBO) datasourceJdbcMapper.findDatasourceById(id);
						return getHandler(bo);
					}
				});
			}else {
				DatasourceJdbcBO bo = (DatasourceJdbcBO) datasourceJdbcMapper.findDatasourceById(id);
				return getHandler(bo);
			}
		}catch(ExecutionException e) {
			throw new DsException("获取数据源异常",e);
		}
		

		return dbHandler;
	}
	
	public DatasourceJdbcBO getDatasource(Long id) throws  DsException {
		return getDatasource(id,true);
	}
	
	public DatasourceJdbcBO getDatasource(Long id, boolean useCache) throws DsException {
		return getHandler(id,useCache).getConfig();
	}
	
	public   void removeCache(Long datasourceId) {
		cacheQuerySqlHandler.invalidate(datasourceId);
	}
	
	public   void closeHandler(DbHandler dbHandler) {
		dbHandler.close();
	}
	
	public  DbHandler getTestHandler(DatasourceJdbcBO datasourceJdbcBO) throws DsException {

		MetaSqlInterface metaSqlInterface = SqlToolFactory.getByDbType(datasourceJdbcBO.getDatasource());
		
		if(datasourceJdbcBO.getDatasource().equals(JdbcConstants.HBASE20XSQL)) {
			initJdbc(datasourceJdbcBO);
			return new Hbase20xsqlHandler(datasourceJdbcBO,metaSqlInterface,true);
		}else {
			return getHandler(datasourceJdbcBO);
		}
		
	}
	
	
	public  DbHandler getHandler(DatasourceJdbcBO datasourceJdbcBO) throws DsException {
		
		initJdbc(datasourceJdbcBO);
		
		MetaSqlInterface metaSqlInterface = SqlToolFactory.getByDbType(datasourceJdbcBO.getDatasource());
		
		if(datasourceJdbcBO.getDatasource().equals(JdbcConstants.MONGODB)) {
			return new MongodbHandler(datasourceJdbcBO);
		}else if(datasourceJdbcBO.getDatasource().equals(JdbcConstants.HBASE20XSQL)) {
			return new Hbase20xsqlHandler(datasourceJdbcBO,metaSqlInterface,false);
		}else {
			DbHandler dbHandler = new RdbmsHandler(datasourceJdbcBO,metaSqlInterface);
			return dbHandler;
		}
		
	}
	
	private void initJdbc(DatasourceJdbcBO datasourceJdbcBO) {
		String userName = AESUtil.decrypt(datasourceJdbcBO.getJdbcUsername());
        //  判断账密是否为密文
        if (userName == null) {
        	userName=datasourceJdbcBO.getJdbcUsername();
        }
        datasourceJdbcBO.setJdbcUsername(userName);
        
        String pwd = AESUtil.decrypt(datasourceJdbcBO.getJdbcPassword());
        if (pwd == null) {
        	pwd=datasourceJdbcBO.getJdbcPassword();
        }
        datasourceJdbcBO.setJdbcPassword(pwd);
	}

	

	
	
	
	

	public String doConvertKeywordsColumn(String dbType, String column) {
        if (column == null) {
            return null;
        }

        column = column.trim();
        column = column.replace("[", "");
        column = column.replace("]", "");
        column = column.replace("`", "");
        column = column.replace("\"", "");
        column = column.replace("'", "");

        switch (dbType) {
            case MYSQL:
                return String.format("`%s`", column);
            case SQL_SERVER:
                return String.format("[%s]", column);
            case POSTGRESQL:
            case ORACLE:
                return String.format("\"%s\"", column);
            default:
                return column;
        }
    }


	
}
